home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-05 | 8.7 KB | 334 lines | [TEXT/PJMM] |
- (******************************************************************************}
- {}
- { CBitmapWindow.p }
- {}
- { SUPERCLASS = CWindow }
- {}
- { Window class that draws via an offscreen bitmap. }
- {}
- { Original author: David Dunham. }
- { For C++ . }
- { Copyright ©1992 Pensée Corporation. }
- { Pensée Corporation }
- { 532 N 71st St }
- { Seattle, WA 98103-5127 }
- {}
- { Pascal Translation: Patrick Hew. }
- { For TCL 1.1.2 .}
- { Copyright © 1995 Patrick Hew. }
- { email: phew@ucc.gu.uwa.edu.au }
- {}
- { CHANGE HISTORY }
- {}
- { 17 Apr 92 DRD Tried offscreen drawing but took it out because CPane uses macPort. }
- { 18 Apr 92 DRD A different approach to offscreen, replacing portBits. }
- { 24 Apr 92 DRD Added (long) cast so we allocate offscreen screen-sized, not hardcoded. }
- { 03 May 92 DRD Made into a stand-alone class, with a bitmap per window. }
- { 30 Aug 92 GHD Moved Prepare() before MakeOffscreen in Update method. }
- { 30 Aug 92 GHD Added Zoom method. }
- {}
- { 02 Jul 95 PH First Pascal translation. }
- { Changed direct allocation of a pointer to allocating and locking a handle. }
- {}
- (******************************************************************************}
-
-
- unit CBitmapWindow;
-
- interface
-
- uses
- TCL;
-
- type
- CBitmapWindow = object(CWindow)
-
- {** Instance data **}
-
- offscreen: BitMap;
- screenData: QDHandle;
-
- {** Construction and destruction **}
-
- procedure IWindowX;
- override;
-
- procedure Free;
- override;
-
- procedure MakeMacWindow (WINDid: Integer);
- override;
-
- {** Size and location **}
-
- procedure ChangeSize (width, height: Integer);
- override;
-
- procedure Zoom (direction: integer);
- override;
-
- {** Drawing **}
-
- procedure MakeOffscreen;
-
- procedure Update;
- override;
-
- end;
-
-
- implementation
-
- uses
- CPane; { Pane_Draw }
-
-
- (******************************************************************************}
- {}
- { IWindowX (OVERRIDE) }
- {}
- { Perform initialization commond to IWindow and INewWindow}
- {}
- { We override here, rather than use the conventional IBitmapWindow, so that we can }
- { use CBitmapWindow as a drop-in replacement for CWindow. No code has to be changed, }
- { except the ancestry. This makes life much simpler when using AppMaker. }
- {}
- {******************************************************************************)
-
- procedure CBitmapWindow.IWindowX;
-
- begin { IWindowX }
- inherited IWindowX;
-
- { We don't have a buffer yet. }
- offscreen.baseAddr := nil;
- screenData := nil;
- end; { IWindowX }
-
-
- (******************************************************************************}
- {}
- { Free (OVERRIDE) }
- {}
- { Get rid of a window and all its panes. }
- {}
- (******************************************************************************}
-
- procedure CBitmapWindow.Free;
-
- var
- theQDHandle: QDHandle;
-
- begin { Free }
- { Free the memory we may have allocated. }
- { Remember - Never pass an instance variable by reference. }
- theQDHandle := screenData;
- screenData := nil;
- ForgetHandle(theQDHandle);
-
- inherited Free;
- end; { Free }
-
-
- (******************************************************************************}
- { MakeMacWindow (OVERRIDE) }
- {}
- { Create a new Toolbox window record using the specified WIND }
- { resource ID. This method creates a non-color window. }
- {}
- { ******************************************************************************)
-
- procedure CBitmapWindow.MakeMacWindow (WINDid: Integer);
-
- var
- savedAlloc: Boolean;
- behind: WindowPtr;
-
- begin { MakeMacWindow }
- savedAlloc := SetAllocation(kAllocCanFail);
-
- if floating then begin
- behind := WindowPtr(-1);
- end { if }
- else begin
- behind := nil;
- end; { else }
-
- macPort := GetNewWindow(WINDid, nil, behind);
-
- savedAlloc := SetAllocation(savedAlloc);
-
- FailNIL(macPort);
- end; { MakeMacWindow }
-
-
- (******************************************************************************}
- {}
- { ChangeSize (OVERRIDE) }
- {}
- { Change the size of a window by specifying the width and height }
- { in pixels. Window cannot be made larger than the maximum size }
- { specified by its sizeRect instance variable. }
- {}
- { ******************************************************************************)
-
- procedure CBitmapWindow.ChangeSize (width, height: Integer);
-
- var
- theQDHandle: QDHandle;
-
- begin { ChangeSize }
- { Our offscreen bitmap is no longer the right size. }
- { Remember - Never pass an instance variable by reference. }
- theQDHandle := screenData;
- screenData := nil;
- ForgetHandle(theQDHandle);
-
- inherited ChangeSize(width, height);
- end; { ChangeSize }
-
-
- (******************************************************************************}
- {}
- { Zoom (OVERRIDE) }
- {}
- { Zoom a window out to a standard size or in to its original size. }
- {}
- {******************************************************************************)
-
- procedure CBitmapWindow.Zoom (direction: integer);
-
- var
- theQDHandle: QDHandle;
-
- begin { Zoom }
- { Our offscreen bitmap is no longer the right size. }
- { Remember - Never pass an instance variable by reference. }
- theQDHandle := screenData;
- screenData := nil;
- ForgetHandle(theQDHandle);
-
- inherited Zoom(direction);
- end; { Zoom }
-
-
- (******************************************************************************}
- {}
- { MakeOffscreen }
- {}
- { Initialize the offscreen bitmap. }
- {}
- { For further discussion, refer to THINK Reference Ver2.00, "Creating Offscreen Bitmaps". }
- { ******************************************************************************)
-
- procedure CBitmapWindow.MakeOffscreen;
-
- begin { MakeOffscreen }
- { We don't want to call this twice. }
- ASSERT(screenData = nil);
-
- { We make an offscreen BitMap as large as the window. }
- offscreen.bounds := macPort^.portRect;
-
- { rowBytes is size of row, rounded up to an even number of bytes. }
- offscreen.rowBytes := BSL(BSR((offscreen.bounds.right - offscreen.bounds.left + 15), 4), 1);
-
- { To minimize clogging of the heap, we allocate the offscreen memory here }
- { as a handle. When we draw, we will lock the handle and set offscreen.baseAddr }
- { to point to the block which is being handled. }
- screenData := QDHandle(NewHandleCanFail(longint(offscreen.rowBytes * (offscreen.bounds.bottom - offscreen.bounds.top))));
-
- FailNIL(screenData);
- end; { MakeOffscreen }
-
-
- (******************************************************************************}
- { Update}
- {}
- { Update the contents of a window using an offscreen BitMap. (Because we’re }
- { using a BitMap, the window cannot be a color GrafPort). Since Panes refer }
- { to macPort, and expect it to be a WindowPeek, we can’t simply replace the port, }
- { so we replace its portBits. }
- {}
- { Drawing seems substantially slower, but it’s without flicker. }
- {}
- {******************************************************************************)
-
- procedure CBitmapWindow.Update;
-
- var
- savePort: GrafPtr; { The current port. }
- updateRect: Rect; { Bounding box of the update region. }
- savePortBits: BitMap; { Window's original portBits. }
-
- begin { Update }
- { Save the original port. }
- GetPort(savePort);
-
- { Set up the Window's port. }
- Prepare;
-
- { If we don't have an offscreen bitmap built yet, make it. }
- if screenData = nil then begin
- MakeOffscreen;
- end; { if }
- ASSERT(screenData <> nil);
-
- { Lock the block of screen data, and set the offscreen port }
- { to point to it. }
- HLockHi(screenData);
- offscreen.baseAddr := screenData^;
-
- { Save the previous bitmap. }
- savePortBits := thePort^.portBits;
-
- { Draw offscreen. }
- { Make sure that the window is at corner. }
- SetPortBits(offscreen);
- MovePortTo(0, 0);
-
- { Get the bounding box of the update region, so we can draw only the panes }
- { that intersect it. It's still in screen coordinates, so we have to offset it. }
- updateRect := WindowPeek(macPort)^.updateRgn^^.rgnBBox;
- OffsetRect(updateRect, savePortBits.bounds.left, savePortBits.bounds.top);
-
- { Draw all subviews. }
- if (itsSubviews <> nil) then begin
- { Clip to the update region. }
- ClipRect(updateRect);
-
- { Erase the update region. }
- EraseRect(updateRect);
-
- itsSubviews.DoForEach1(Pane_Draw, @updateRect);
- end; { if }
-
- { Restore the previous bitmap. }
- SetPortBits(savePortBits);
- MovePortTo(-savePortBits.bounds.left, -savePortBits.bounds.top);
-
- { Start the update process. }
- BeginUpdate(macPort);
-
- { Clip to the entire window. }
- SetOrigin(0, 0);
- ClipRect(thePort^.portRect);
-
- { Copy from offscreen to the update region. }
- CopyBits(offscreen, savePortBits, updateRect, updateRect, srcCopy, nil);
-
- { End the update process. }
- EndUpdate(macPort);
-
- { Restore the original port. }
- SetPort(savePort);
-
- ForceNextPrepare;
-
- { Unlock the block of screen data, and reset the offscreen port. }
- offscreen.baseAddr := nil;
- HUnlock(screenData);
- end; { Update }
-
-
- end. { CBitmapWindow }